#pragma once

#include "Window.hpp"
#include "Desktop.hpp"




struct ENGINE_UI_API StandardButton
{
	enum Type
	{
		Ok,
		Cancel,
		Yes,
		No,
		Apply,
	};

	static QString text(Type type);
};
///////////////////////////////////////////////////////////////////////////////////////////////

/**
 * This class offers the ability to show the user a modal Dialog.
 * When created, the dialog places itself on top of all other windows of
 * it's PARENT, hence it will be clever to choose the desktop for the parent, otherwise
 * the dialog might not appear on top of everything.
 * In order to keep the dialog running, one must call doModal() every update (preferably
 * after the Ui update, but not necessarily) and then destroy the dialog AFTER it returned
 * the button that has been clicked. If the dialog is destroyed before, it's destructor
 * throws a programming_error exception.
 *
 * You can manually force the dialog to close by calling: forceClick with the desired button
 * (again, preferably before doModal) and then doModal will return that button and remove it
 * from the modal widget's stack.
 */
class ENGINE_UI_API Dialog : public Window
{
public:

	typedef QVector<StandardButton::Type>           StandardButtons;
	typedef boost::optional<StandardButton::Type>   OptButton;

private:

	bool         m_modal;
	TextPtr      m_caption;
	WidgetPtr    m_buttons;
	WidgetList   m_buttonList;
	OptButton    m_clickedButton;

public:

	/**
	 * Creates a Dialog with NO buttons at all.
	 * They must be manually added.
	 */
	Dialog(const QString& text, const QString& title, Desktop* parent, Widgets::Type finalType = Widgets::Dialog);

	/**
	 * Destroys the dialog.
	 */
	virtual ~Dialog();



	/**
	 * Calling this function keeps checking if any button of the dialog has been clicked, or not.
	 * Once a button has been clicked, the dialog will close and the Id of the button is returned.
	 *
	 * @see StandardButtons::Type
	 */
	OptButton doModal();

	/**
	 * Calling this function forces the dialog to be closed.
	 * doModal will then return the button type, given here.
	 */
	void forceClick(StandardButton::Type which);



	/**
	 * Sets the text of the dialog.
	 */
	void setCaption(const QString& text);



	/**
	 * Adds the given button to the dialog.
	 */
	void addButton(StandardButton::Type which);

	/**
	 * Adds the given list of buttons to the dialog.
	 */
	void addButtons(StandardButtons buttons);

protected:

	/**
	 * Get the type of this widget.
	 */
	virtual Widgets::Type type() const;

	/**
	 * Updates this dialog.
	 */
	virtual void update(NestedState& state);

private:

	void onButtonClicked(Widget*, StandardButton::Type which);
};
///////////////////////////////////////////////////////////////////////////////////////////////

DEFINE_LOOSE_PTR(Dialog);
